home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / initramfs-tools / hooks / cryptroot < prev    next >
Text File  |  2009-10-14  |  11KB  |  494 lines

  1. #!/bin/sh
  2.  
  3. PREREQ=""
  4.  
  5. prereqs()
  6. {
  7.     echo "$PREREQ"
  8. }
  9.  
  10. case $1 in
  11. prereqs)
  12.     prereqs
  13.     exit 0
  14.     ;;
  15. esac
  16.  
  17. . /usr/share/initramfs-tools/hook-functions
  18.  
  19. get_root_device() {
  20.     local device mount type options dump pass
  21.  
  22.     if [ ! -r /etc/fstab ]; then
  23.         return 1
  24.     fi
  25.  
  26.     grep '^[^#]' /etc/fstab | \
  27.     while read device mount type options dump pass; do
  28.         if [ "$mount" = "/" ]; then
  29.             echo "$device"
  30.             return
  31.         fi
  32.     done
  33. }
  34.  
  35. get_resume_devices() {
  36.     local device opt count dupe candidates devices
  37.     candidates=""
  38.  
  39.     # First, get a list of potential resume devices
  40.  
  41.     # uswsusp
  42.     if [ -e /etc/uswsusp.conf ]; then
  43.         device=$(sed -rn 's/^resume device[[:space:]]*[:=][[:space:]]*// p' /etc/uswsusp.conf)
  44.         if [ -n "$device" ]; then
  45.             candidates="$candidates $device"
  46.         fi
  47.     fi
  48.  
  49.     # uswsusp - again...
  50.     if [ -e /etc/suspend.conf ]; then
  51.         device=$(sed -rn 's/^resume device[[:space:]]*[:=][[:space:]]*// p' /etc/suspend.conf)
  52.         if [ -n "$device" ]; then
  53.             candidates="$candidates $device"
  54.         fi
  55.     fi
  56.  
  57.     # regular swsusp
  58.     for opt in $(cat /proc/cmdline); do
  59.         case $opt in
  60.         resume=*)
  61.             device="${opt#resume=}"
  62.             candidates="$candidates $device"
  63.             ;;
  64.         esac
  65.     done
  66.  
  67.     # initramfs-tools
  68.     if [ -e /etc/initramfs-tools/conf.d/resume ]; then
  69.         device=$(sed -rn 's/^RESUME[[:space:]]*=[[:space:]]*// p' /etc/initramfs-tools/conf.d/resume)
  70.         if [ -n "$device" ]; then
  71.             candidates="$candidates $device"
  72.         fi
  73.     fi
  74.  
  75.     # Now check the sanity of all candidates
  76.     devices=""
  77.     count=0
  78.     for device in $candidates; do
  79.         # Weed out clever defaults
  80.         if [ "$device" = "<path_to_resume_device_file>" ]; then
  81.             continue
  82.         fi
  83.  
  84.         # Weed out duplicates
  85.         dupe=0
  86.         for opt in $devices; do
  87.             if [ "$device" = "$opt" ]; then
  88.                 dupe=1
  89.             fi
  90.         done
  91.         if [ $dupe -eq 1 ]; then
  92.             continue
  93.         fi
  94.  
  95.         # This device seems ok
  96.         devices="$devices $device"
  97.         count=$(( $count + 1 ))
  98.     done
  99.  
  100.     if [ $count -gt 1 ]; then
  101.         echo "cryptsetup: WARNING: found more than one resume device candidate:" >&2
  102.         for device in $devices; do
  103.             echo "                     $device" >&2
  104.         done
  105.     fi
  106.  
  107.     if [ $count -gt 0 ]; then
  108.         echo $devices
  109.     fi
  110.  
  111.     return 0
  112. }
  113.  
  114. node_is_in_crypttab() {
  115.     local node
  116.     node="$1"
  117.  
  118.     grep -q ^$node /etc/crypttab
  119.     return $?
  120. }
  121.  
  122. get_lvm_deps() {
  123.     local node deps maj min depnode
  124.     node="$1"
  125.  
  126.     if [ -z $node ]; then
  127.         echo "cryptsetup: WARNING: get_lvm_deps - invalid arguments" >&2
  128.         return 1
  129.     fi
  130.  
  131.     if ! deps=$(dmsetup deps "$node" 2> /dev/null | sed 's/[^:]*: *//;s/[ (]//g;s/)/ /g'); then
  132.         echo "cryptsetup: WARNING: failed to find deps for $node" >&2
  133.         return 1
  134.     fi
  135.  
  136.     # We should now have a list of major,minor pairs, e.g. "3,2 3,3"
  137.     for dep in $deps; do
  138.         maj=${dep%,*}
  139.         min=${dep#*,}
  140.         depnode=$(dmsetup ls | sed -n "s/\\([^ ]*\\) *($maj, $min)/\\1/p" | sed -e "s/[ \t]*$//")
  141.         if [ -z "$depnode" ]; then
  142.             continue
  143.         fi
  144.         if [ "$(dmsetup table "$depnode" 2> /dev/null | cut -d' ' -f3)" != "crypt" ]; then
  145.             get_lvm_deps "$depnode"
  146.             continue
  147.         fi
  148.         echo "$depnode"
  149.     done
  150.  
  151.     return 0
  152. }
  153.  
  154. get_device_opts() {
  155.     local target source link extraopts rootopts opt
  156.     target="$1"
  157.     extraopts="$2"
  158.     KEYSCRIPT=""
  159.     OPTIONS=""
  160.  
  161.     if [ -z "$target" ]; then
  162.         echo "cryptsetup: WARNING: get_device_opts - invalid arguments" >&2
  163.         return 1
  164.     fi
  165.  
  166.     opt=$( grep ^$target /etc/crypttab | head -1 | sed 's/[[:space:]]\+/ /g' )
  167.     source=$( echo $opt | cut -d " " -f2 )
  168.     key=$( echo $opt | cut -d " " -f3 )
  169.     rootopts=$( echo $opt | cut -d " " -f4- )
  170.  
  171.     if [ -z "$opt" ] || [ -z "$source" ] || [ -z "$key" ] || [ -z "$rootopts" ]; then
  172.         echo "cryptsetup: WARNING: invalid line in /etc/crypttab - $opt" >&2
  173.         return 1
  174.     fi
  175.  
  176.     # Sanity checks for $source
  177.     if [ -h "$source" ]; then
  178.         link=$(readlink -nqe "$source")
  179.         if [ -z "$link" ]; then
  180.             echo "cryptsetup: WARNING: $source is a dangling symlink" >&2
  181.             return 1
  182.         fi
  183.  
  184.         if [ "$link" != "${link#/dev/mapper/}" ]; then
  185.             echo "cryptsetup: NOTE: using $link instead of $source for $target" >&2
  186.             source="$link"
  187.         fi
  188.     fi
  189.  
  190.     # Sanity checks for $key
  191.     if [ "$key" = "/dev/random" ] || [ "$key" = "/dev/urandom" ]; then
  192.         echo "cryptsetup: WARNING: target $target has a random key, skipped" >&2
  193.         return 1
  194.     fi
  195.  
  196.     if [ -n "$extraopts" ]; then
  197.         rootopts="$extraopts,$rootopts"
  198.     fi
  199.  
  200.     # We have all the basic options, let's go trough them
  201.     OPTIONS="target=$target,source=$source,key=$key"
  202.     local IFS=", "
  203.     unset HASH_FOUND
  204.     unset LUKS_FOUND
  205.     for opt in $rootopts; do
  206.         case $opt in
  207.             cipher=*)
  208.                 OPTIONS="$OPTIONS,$opt"
  209.                 ;;
  210.             hash=*)
  211.                 OPTIONS="$OPTIONS,$opt"
  212.                 HASH_FOUND=1
  213.                 ;;
  214.             size=*)
  215.                 OPTIONS="$OPTIONS,$opt"
  216.                 ;;
  217.             lvm=*)
  218.                 OPTIONS="$OPTIONS,$opt"
  219.                 ;;
  220.             keyscript=*)
  221.                 opt=${opt#keyscript=}
  222.                 if [ ! -x "/lib/cryptsetup/scripts/$opt" ] && [ ! -x "$opt" ]; then
  223.                     echo "cryptsetup: WARNING: target $target has an invalid keyscript, skipped" >&2
  224.                     return 1
  225.                 fi
  226.                 KEYSCRIPT="$opt"
  227.                 OPTIONS="$OPTIONS,keyscript=/lib/cryptsetup/scripts/$(basename "$opt")"
  228.                 ;;
  229.             tries=*)
  230.                 OPTIONS="$OPTIONS,$opt"
  231.                 ;;
  232.             luks)
  233.                 LUKS_FOUND=1
  234.                 ;;
  235.             *)
  236.                 # Presumably a non-supported option
  237.                 ;;
  238.         esac
  239.     done
  240.  
  241.     # Warn for missing hash option, unless we have a LUKS partition
  242.     if [ -z "$HASH_FOUND" ] && [ -z "$LUKS_FOUND" ]; then
  243.         echo "WARNING: Option hash missing in crypttab for target $target, assuming ripemd160." >&2
  244.         echo "         If this is wrong, this initramfs image will not boot." >&2
  245.         echo "         Please read /usr/share/doc/cryptsetup/README.initramfs.gz and add" >&2
  246.         echo "         the correct hash option to your /etc/crypttab."  >&2
  247.     fi
  248.  
  249.     # If keyscript is set, the "key" is just an argument to the script
  250.     if [ "$key" != "none" ] && [ -z "$KEYSCRIPT" ]; then
  251.         echo "cryptsetup: WARNING: target $target uses a key file, skipped" >&2
  252.         return 1
  253.     fi
  254. }
  255.  
  256. get_device_modules() {
  257.     local node value cipher blockcipher ivhash
  258.     node="$1"
  259.  
  260.     # Check the ciphers used by the active root mapping
  261.     value=$(dmsetup table "$node" | cut -d " " -f4)
  262.     cipher=$(echo "$value" | cut -d ":" -f1 | cut -d "-" -f1)
  263.     blockcipher=$(echo "$value" | cut -d ":" -f1 | cut -d "-" -f2)
  264.     ivhash=$(echo "$value" | cut -d ":" -s -f2)
  265.  
  266.     if [ -n "$cipher" ]; then
  267.         echo "$cipher"
  268.     else
  269.         return 1
  270.     fi
  271.  
  272.     if [ -n "$blockcipher" ] && [ "$blockcipher" != "plain" ]; then
  273.         echo "$blockcipher"
  274.     fi
  275.  
  276.     if [ -n "$ivhash" ] && [ "$ivhash" != "plain" ]; then
  277.         echo "$ivhash"
  278.     fi
  279.     return 0
  280. }
  281.  
  282. canonical_device() {
  283.     local dev altdev original
  284.     dev="$1"
  285.  
  286.     altdev="${dev#LABEL=}"
  287.     if [ "$altdev" != "$dev" ]; then
  288.         dev="/dev/disk/by-label/$altdev"
  289.     fi
  290.  
  291.     altdev="${dev#UUID=}"
  292.     if [ "$altdev" != "$dev" ]; then
  293.         dev="/dev/disk/by-uuid/$altdev"
  294.     fi
  295.  
  296.     original=$dev
  297.     if [ -h "$dev" ]; then
  298.         dev=$(readlink -e "$dev")
  299.     fi
  300.  
  301.     altdev="${dev#/dev/mapper/}"
  302.     if [ "$altdev" != "$dev" ]; then
  303.         echo "$altdev"
  304.         return 0
  305.     elif [ "x${original%/dev/disk/by-*/*}" = "x" ]; then
  306.         # support crypttab UUID/LABEL entries
  307.         # this is a /dev/disk/by-*/ path so return just the 'basename'
  308.         echo "${original##/dev/disk/by-*/}"
  309.         return 0
  310.     fi
  311.  
  312.     return 1
  313. }
  314.  
  315. add_device() {
  316.     local node nodes opts lastopts i count
  317.     nodes="$1"
  318.     opts=""     # Applied to all nodes
  319.     lastopts="" # Applied to last node
  320.  
  321.     if [ -z "$nodes" ]; then
  322.         return 0
  323.     fi
  324.  
  325.     # Check that it is a node under /dev/mapper/
  326.     nodes=$(canonical_device "$nodes") || return 0
  327.  
  328.     # Can we find this node in crypttab
  329.     if ! node_is_in_crypttab "$nodes"; then
  330.         # dm node but not in crypttab, is it a lvm device backed by dm-crypt nodes?
  331.         lvmnodes=$(get_lvm_deps "$nodes") || return 1
  332.  
  333.         # not backed by any dm-crypt nodes; stop here
  334.         if [ -z "$lvmnodes" ]; then
  335.             return 0
  336.         fi
  337.  
  338.         # It is a lvm device!
  339.         lastopts="lvm=$nodes"
  340.         nodes="$lvmnodes"
  341.     fi
  342.  
  343.     # Prepare to setup each node
  344.     count=$(echo "$nodes" | wc -w)
  345.     i=1
  346.     for node in $nodes; do
  347.         # Prepare the additional options
  348.         if [ $i -eq $count ]; then
  349.             if [ -z "$opts" ]; then
  350.                 opts="$lastopts"
  351.             else
  352.                 opts="$opts,$lastopts"
  353.             fi
  354.         fi
  355.  
  356.         # Get crypttab root options
  357.         if ! get_device_opts "$node" "$opts"; then
  358.             continue
  359.         fi
  360.         echo "$OPTIONS" >> "$DESTDIR/conf/conf.d/cryptroot"
  361.  
  362.         # If we have a keyscript, make sure it is included
  363.         if [ -n "$KEYSCRIPT" ]; then
  364.             if [ ! -d "$DESTDIR/lib/cryptsetup/scripts" ]; then
  365.                 mkdir -p "$DESTDIR/lib/cryptsetup/scripts"
  366.             fi
  367.  
  368.             if [ -e "/lib/cryptsetup/scripts/$KEYSCRIPT" ]; then
  369.                 copy_exec "/lib/cryptsetup/scripts/$KEYSCRIPT" /lib/cryptsetup/scripts
  370.             elif [ -e "$KEYSCRIPT" ]; then
  371.                 copy_exec "$KEYSCRIPT" /lib/cryptsetup/scripts
  372.             else
  373.                 echo "cryptsetup: WARNING: failed to find keyscript $KEYSCRIPT" >&2
  374.                 continue
  375.             fi
  376.         fi
  377.  
  378.         # Calculate needed modules
  379.         modules=$(get_device_modules $node | sort | uniq)
  380.         if [ -z "$modules" ]; then
  381.             echo "cryptsetup: WARNING: failed to determine cipher modules to load for $node" >&2
  382.             continue
  383.         fi
  384.         echo dm_mod
  385.         echo dm_crypt
  386.         echo "$modules"
  387.  
  388.         i=$(( $i + 1 ))
  389.     done
  390.  
  391.     return 0
  392. }
  393.  
  394. add_crypto_modules() {
  395.     local mod file altmod found genericfound
  396.     mod="$1"
  397.     found=""
  398.     genericfound=""
  399.  
  400.     if [ -z "$mod" ]; then
  401.         return 1
  402.     fi
  403.  
  404.     # We have several potential sources of modules (in order of preference):
  405.     #
  406.     #   a) /lib/modules/$VERSION/kernel/arch/$ARCH/crypto/$mod-$specific.ko
  407.     #   b) /lib/modules/$VERSION/kernel/crypto/$mod_generic.ko
  408.     #   c) /lib/modules/$VERSION/kernel/crypto/$mod.ko
  409.     #
  410.     # and (currently ignored):
  411.     #
  412.     #   d) /lib/modules/$VERSION/kernel/drivers/crypto/$specific-$mod.ko
  413.  
  414.     for file in $(find "$MODULESDIR/kernel/arch/" -name "$mod-*.ko"); do
  415.         altmod="${file##*/}"
  416.         altmod="${altmod%.ko}"
  417.         manual_add_modules "$altmod"
  418.         found="yes"
  419.     done
  420.  
  421.     for file in $(find "$MODULESDIR/kernel/crypto/" -name "${mod}_generic.ko"); do
  422.         altmod="${file##*/}"
  423.         altmod="${altmod%.ko}"
  424.         manual_add_modules "$altmod"
  425.         found="yes"
  426.         genericfound="yes"
  427.     done
  428.  
  429.     if [ -z "$genericfound" ]; then
  430.         for file in $(find "$MODULESDIR/kernel/crypto/" -name "${mod}.ko"); do
  431.             altmod="${file##*/}"
  432.             altmod="${altmod%.ko}"
  433.             manual_add_modules "$altmod"
  434.             found="yes"
  435.         done
  436.     fi
  437.  
  438.     if [ -z "$found" ]; then
  439.         return 1
  440.     fi
  441.  
  442.     return 0
  443. }
  444.  
  445. #
  446. # Begin real processing
  447. #
  448.  
  449. setup="no"
  450. rootdev=""
  451. resumedevs=""
  452.  
  453. # Find the root and resume device(s)
  454. if [ -r /etc/crypttab ]; then
  455.     rootdev=$(get_root_device)
  456.     if [ -z "$rootdev" ]; then
  457.         echo "cryptsetup: WARNING: could not determine root device from /etc/fstab" >&2
  458.     fi
  459.     resumedevs=$(get_resume_devices)
  460. fi
  461.  
  462. # Load the config opts and modules for each device
  463. for dev in $rootdev $resumedevs; do
  464.     if ! modules=$(add_device "$dev"); then
  465.         echo "cryptsetup: FAILURE: could not determine configuration for $dev" >&2
  466.         continue
  467.     fi
  468.  
  469.     setup="yes"
  470.     for mod in $modules; do
  471.         add_crypto_modules $mod
  472.     done
  473. done
  474.  
  475. # With large initramfs, we always add a basic subset of modules
  476. if [ "$MODULES" != "dep" ]; then
  477.     for mod in aes sha256 cbc; do
  478.         add_crypto_modules $mod
  479.     done
  480. fi
  481.  
  482. # See if we need to add the basic components
  483. if [ "$MODULES" != "dep" ] || [ "$setup" = "yes" ]; then
  484.     for mod in dm_mod dm_crypt; do
  485.         manual_add_modules $mod
  486.     done
  487.  
  488.     copy_exec /sbin/cryptsetup
  489.     copy_exec /sbin/dmsetup
  490.     copy_exec /lib/cryptsetup/askpass
  491. fi
  492.  
  493. exit 0
  494.